/**
  * @file 		osal.h
  * @brief		轮询式任务调度系统
  *
  * @copyright  Copyright (c) 2017~2020 ShenZhen Dxtc Technology Co., Ltd. 
  * All rights reserved.
  * 
  * @version    v3.1
  * @author		FengLi
  * @date 		2020-11-25
  * 
  * @note		鼎新同创·智能锁
  * 
  * @par 修改日志:
  * <1> 2020/11/25 v3.1 FengLi 创建初始版本
  *******************************************************************/
#ifndef __OSAL_H__
#define __OSAL_H__
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include "export.h"
#include "net_t.h"


#define C_NONE         "\033[m"               ///< (显色)结束
#define C_BLACK        "\033[0;30;47m"        ///< 黑色
#define C_DARY_GRAY    "\033[1;30m"           ///< 深灰
#define C_RED          "\033[0;31m"           ///< 红色
#define C_LIGHT_RED    "\033[1;31m"           ///< 浅红
#define C_GREEN        "\033[0;32m"           ///< 绿色
#define C_LIGHT_GREEN  "\033[1;32m"           ///< 浅绿
#define C_BROWN        "\033[0;33m"           ///< 棕色
#define C_YELLOW       "\033[1;33m"           ///< 黄色
#define C_BLUE         "\033[0;34m"           ///< 蓝色
#define C_LIGHT_BLUE   "\033[1;34m"           ///< 浅蓝
#define C_PURPLE       "\033[0;35m"           ///< 紫色
#define C_LIGHT_PURPLE "\033[1;35m"           ///< 浅紫
#define C_CYAN         "\033[0;36m"           ///< 蓝绿
#define C_LIGHT_CYAN   "\033[1;36m"           ///< 浅青绿
#define C_LIGHT_GRAY   "\033[0;37m"           ///< 浅灰
#define C_WHITE        "\033[1;37m"           ///< 白色
#define C_COLOR        "\033[7m"              ///< 反显

uint32_t OSAL_GetTickCount(void);

/** @brief   获取__FILE里面文件名信息 */
#ifdef  WINDOWS_FILE_PATH
#define SHORT_FILE                      strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__
#else
#define SHORT_FILE                      strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__
#endif

/** @brief   详细日志打印宏（打印运行函数、文件及行数等信息 ） */
#if defined(OSAL_LOG_DISABLE)
#define OSAL_LOG(format, ...)
#define __OSAL_LOG(format, ...)
#else
#define OSAL_LOG(format, ...)           printf("[%d][%s:%05d] "format"\r\n",OSAL_GetTickCount(),SHORT_FILE,__LINE__, ##__VA_ARGS__)															 
#define __OSAL_LOG(format, ...)         printf(format, ##__VA_ARGS__)  ///< 普通日志打印宏      
#endif

//#define SYS_CALL_LOG(format, ...)       OSAL_LOG(C_LIGHT_RED C_COLOR format C_NONE, ##__VA_ARGS__)

/** @brief   计算过去的时间 */
#define OSAL_PastTime(current_time, last_time)     ( (current_time >= last_time) ? (current_time - last_time) : (UINT32_MAX - last_time + current_time) )

/** @brief   计算数组长度 */
#define OSAL_LENGTH(array)  ( sizeof(array) / sizeof(array[0]) )

/** @brief   计算结构体成员的地址偏移量 */
#define OSAL_OFFSET(type, member) ((unsigned int)(&(((typeof(type) *)0)->member)))

/** @brief   32位字节序转换 */
#define OSAL_SWAP32(x) ((uint32_t)(                         \
        (((uint32_t)(x) & (uint32_t)0x000000ff) << 24) |    \
        (((uint32_t)(x) & (uint32_t)0x0000ff00) <<  8) |    \
        (((uint32_t)(x) & (uint32_t)0x00ff0000) >>  8) |    \
        (((uint32_t)(x) & (uint32_t)0xff000000) >> 24)))

/** @brief   32位字节序转换 */
#define OSAL_SWAP16(x) ((uint16_t)(                         \
        (((uint16_t)(x) & (uint16_t)0x00ff) <<  8) |        \
        (((uint16_t)(x) & (uint16_t)0xff00) >>  8)))

#define OSAL_BCD2DEC(bcd)  ( (bcd >> 4) * 10 + (bcd & 0XF)  ) ///< BCD 转 十进制 - 数据格式转换 
#define OSAL_DEC2BCD(dec)  ( ((dec / 10) << 4) | (dec % 10) ) ///< 十进制 转 BCD - 数据格式转换 


#ifndef KOS_PARAM_SLEEP_FUNC
/** @brief   配置KOS是否支持睡眠功能（屏蔽睡眠功能可以省1.6KB代码空间） */
#define	KOS_PARAM_SLEEP_FUNC    (1)
#endif

#ifndef KOS_PARAM_WAKE_INTERVAL
/** @brief   系统休眠状态（deep-sleep）下的唤醒间隔 */
#define	KOS_PARAM_WAKE_INTERVAL (10000)
#endif

#ifndef KOS_PARAM_MBOX_LEN
/** @brief   TASK邮箱长度 */
#define KOS_PARAM_MBOX_LEN      (20)
#endif


/** @brief   时间类型定义  */
typedef enum 
{
    T_UTC = 0,       ///< UTC时间戳类型
    T_TIME = !T_UTC  ///< 年月日时分秒类型
}TimeType;

/** @brief   FLAHS类型定义  */
typedef enum
{
    RESET = 0,    ///< 假
    SET = !RESET  ///< 真
}FlagStatus, ITStatus;

/** @brief   功能状态类型定义  */
typedef enum
{
    DISABLE = 0,      ///< 禁能
    ENABLE = !DISABLE ///< 使能
}FunctionalState;

/** @brief   错误状态类型定义  */
typedef enum
{
    ERROR = 0,       ///< 错误
    SUCCESS = !ERROR ///< 成功
}ErrorStatus;

typedef void* RingBufferHandle_t; ///< 环形缓存句柄
typedef void* AppHandle_t;        ///< 应用句柄
typedef void* TimerHandle_stu_t;  ///< 定时器句柄
typedef void* SuperQueueHandle_t; ///< 队列句柄
typedef int (*QueueCb_fun_t)(uint32_t param, void *data, uint16_t size); ///< 遍历队列的回调函数类型


/** @brief   任务状态  */
typedef enum
{
    TASK_STA_NORMAL, ///< 正常状态
    TASK_STA_ACTIVE, ///< 活跃状态（任务处于活跃状态系统不会休眠）
}TaskStatus_enum_t;

/** @brief   Timer状态
  *          说明：国芯那种平台休眠状态下硬件无法支持Timer运行
  *          所以在系统休眠前要把Timer状态设置成
  *          TIM_STOP或者TIM_RUN_ONLY_WAKE或者删除Timer
  */
typedef enum
{
    TIM_STOP           = 0x00, ///< 停止状态
    TIM_RUN_ONLY_WAKE  = 0x01, ///< 仅唤醒状态运行
    TIM_RUN_WAKE_SLEEP = 0x03, ///< 唤醒和休眠都运行
}TimerStatus_enum_t;

/** @brief   事件优先级  */
typedef enum
{
	EVT_PRIORITY_HIGH   = 0, ///< 高优先级事件
	EVT_PRIORITY_MEDIUM = 1, ///< 中优先级事件
	EVT_PRIORITY_LOW    = 2, ///< 低优先级事件
}EventPriority_enum_t;

/** @brief   加解密参数  */
typedef enum
{
    TDES_ENCRYPTION,    ///< TDES加密
    TDES_DECRYPTION,    ///< TDES解密
    AES128_ENCRYPTION,  ///< AES加密
    AES128_DECRYPTION,  ///< AES解密
    AES256_ENCRYPTION,  ///< AES加密
    AES256_DECRYPTION,  ///< AES解密
    CALC_RANDOM_NUMBER, ///< 计算随机数
    CALC_MD5,           ///< 计算MD5
    CALC_SHA1,          ///< 计算SHA1
    CALC_SHA256,        ///< 计算SHA256
    CALC_CRC8,          ///< 计算CRC8
    CALC_CRC16,         ///< 计算CRC16
    CALC_CRC32,         ///< 计算CRC32
    AES128_ENCRYPTION_PKCS7,  ///< AES加密_PKCS7
    AES128_DECRYPTION_PKCS7,  ///< AES解密_PKCS7
}Crypto_enum_t;

/** @brief   特殊的标志宏定义  */
#define UINT32_FLAG            (0x55AAF0F0)

#define EVENT_SYS_MBOX         (0X80000000)///< 系统邮箱事件 - 系统事件
#define EVENT_SYS_START        (0X40000000)///< 系统启动事件 - 系统事件
#define EVENT_SYS_SLEEP        (0X20000000)///< 系统休眠事件 - 系统事件
#define EVENT_SYS_ISR          (0X10000000)///< 系统中断事件 - 系统事件

#define TASK_ID_IDLE   ( 0XFE ) ///< 空闲任务ID - 两个系统任务
#define TASK_NO_TASK   ( 0XFF ) ///< OSAL调度器ID - 两个系统任务

#define APP_NO_APP     ( 0XFF ) ///< 错误的APP-ID（当前没有在应用层执行） - 两个系统APP-ID 
#define APP_ID_CB      ( 0XFE ) ///< 回调的APP-ID（当前正在执行应用层回调函数）- 两个系统APP-ID 



/* 内存管理API */
size_t OSAL_GetFreeHeapSize(void);           ///< 获取当前未分配的内存堆大小
size_t OSAL_GetMinimumEverFreeHeapSize(void);///< 获取未分配的内存堆历史最小值
#ifndef KOS_PARAM_HEAP_DEBUG
void *OSAL_Malloc(size_t xWantedSize);       ///< 申请内存
void  OSAL_Free(void *pv);                   ///< 内存释放函数  
#else
void *OSAL_MallocMem(size_t xWantedSize);    ///< 申请内存
void  OSAL_FreeMem(void *pv);                ///< 内存释放函数  
#define OSAL_Free(p)                                            \
({                                                              \
    __OSAL_LOG("free(%08X) %s:%d\r\n", p, SHORT_FILE, __LINE__);\
    OSAL_FreeMem(p);                                            \
})
#define OSAL_Malloc(len)                                                    \
({                                                                          \
    void *pp = OSAL_MallocMem(len);                                         \
    __OSAL_LOG("malloc(%08X,%d) %s:%d\r\n", pp, len, SHORT_FILE, __LINE__); \
    pp ? pp : pp;                                                           \
})
#endif


/* 事件操作API */
ErrorStatus OSAL_EventGenerictCreate(uint16_t comp_id, uint32_t events, uint32_t xTicks, FlagStatus repeat, EventPriority_enum_t priority);
ErrorStatus OSAL_EventCreateFromISR(uint16_t copm_id);
ErrorStatus OSAL_EventDelete(uint16_t comp_id, uint32_t events);
#define OSAL_EventSingleCreate(comp_id, events, xTicks, priority)   OSAL_EventGenerictCreate(comp_id, events, xTicks, RESET, priority)  ///< 通用的事件创建API(单次)
#define OSAL_EventRepeatCreate(comp_id, events, xTicks, priority)   OSAL_EventGenerictCreate(comp_id, events, xTicks, SET, priority)    ///< 通用的事件创建API(重复)


/* 消息发布与订阅API */
ErrorStatus OSAL_MessagePublish(void *msg, uint16_t len);
ErrorStatus OSAL_MessageSubscribe(AppHandle_t handle, uint16_t comp_id, void(*cb)(void*, uint16_t));
uint8_t OSAL_MessageGetSource(uint8_t *esn);
#define OSAL_MessagePublishSysMsg(msg, len) OSAL_MessagePublish(msg, (len | 0x8000))
#define OSAL_MessagePublishErrorCode(type, value) {uint16_t data = (((value) << 8) | (uint8_t)(type)); OSAL_MessagePublishSysMsg(&data, sizeof(data));}


/* APP操作相关API */
AppHandle_t OSAL_AppCreate(char *app_name, ErrorStatus(*pSleepCb)(void));
void OSAL_AppStateSet(char *app_name, FunctionalState state);


/* 定时器API */
ErrorStatus OSAL_TimerSet(TimerHandle_stu_t handle, TimerStatus_enum_t status);
ErrorStatus OSAL_TimerDelete(TimerHandle_stu_t handle);
TimerHandle_stu_t OSAL_TimerCreate(void(*timer_cb)(TimerHandle_stu_t), uint32_t xTicks, FlagStatus repeat);
uint32_t OSAL_TimerGetRemaining(TimerHandle_stu_t handle);


/* 时间API */
ErrorStatus OSAL_TimeGet(void *time, TimeType type);
ErrorStatus OSAL_TimeSet(void *time, TimeType type);
uint32_t OSAL_Time2UTC(uint8_t *pTime, uint8_t bcd);
void OSAL_UTC2Time(uint32_t timestamp, uint8_t *pTime);


/* 环形缓存API */
ErrorStatus OSAL_RingBufferWrite(RingBufferHandle_t handle, void *pData);
ErrorStatus OSAL_RingBufferRead(RingBufferHandle_t handle, void *pData);
ErrorStatus OSAL_RingBufferRead_No_Clear(RingBufferHandle_t handle, void *pData);
RingBufferHandle_t OSAL_RingBufferCreate(uint16_t buffLength, uint16_t itemSize);
ErrorStatus OSAL_RingBufferReset(RingBufferHandle_t handle);
uint32_t OSAL_RingBufferGetValidSize(RingBufferHandle_t handle);


/* 队列API */
ErrorStatus OSAL_QueueReset(SuperQueueHandle_t handle);
SuperQueueHandle_t OSAL_QueueCreate(uint8_t len);
uint16_t OSAL_QueueLenght(SuperQueueHandle_t handle, uint16_t *size);
uint16_t OSAL_QueueReceive(SuperQueueHandle_t handle, void *msg);
uint16_t OSAL_QueueTraverse(SuperQueueHandle_t handle, QueueCb_fun_t cb, uint32_t param);
ErrorStatus OSAL_QueueSend(SuperQueueHandle_t handle, void *msg, uint16_t size, FlagStatus insert);
#define OSAL_QueueSendToBack(handle, msg, size)    OSAL_QueueSend(handle, msg, size, RESET)  ///< 往一个队列最后面插入一个新的消息
#define OSAL_QueueSendToFront(handle, msg, size)   OSAL_QueueSend(handle, msg, size, SET)    ///< 往一个队列最前面插入一个新的消息


/* 邮箱API */
ErrorStatus OSAL_MboxPost(uint16_t comp_id, uint8_t alias, void *msg, uint16_t size);
uint16_t OSAL_MboxAccept(void *msg);
uint16_t OSAL_MboxLenght(uint16_t *size);


/* 系统相关API */

void OSAL_StepTickCount(uint32_t tick);
void OSAL_SysTickHandler(void);
void OSAL_Init(void);
void OSAL_Running(void);
void OSAL_UpdateSleepTime(uint32_t time, uint32_t param);
uint32_t OSAL_GetAutoSleepTime(void);
void OSAL_SystemReset(uint32_t time);
void OSAL_DelayUs(uint32_t time);
void OSAL_KillDog(void);
void OSAL_SetCompAlias(uint8_t alias);
void OSAL_SetTaskStatus(TaskStatus_enum_t status);
ErrorStatus OSAL_WakeupHandler(uint32_t dev);
ErrorStatus OSAL_Crypto(Crypto_enum_t param, void *src, uint32_t len, void *dst, void *key);
ErrorStatus OSAL_NvRead(uint32_t addr, void *out_data, uint32_t len);
ErrorStatus OSAL_NvWrite(uint32_t addr, void *in_data, uint32_t len);
ErrorStatus OSAL_NvReadGlobal(uint16_t comp_id, uint8_t alias, uint32_t addr, void *out_data, uint32_t len);
uint16_t OSAL_CheckPublishQueue(void);
void OSAL_SetWakeupInterval(uint32_t time);
int OSAL_GetSlaveStatus(int channel);


/*  系统API接口  */
#ifndef SYS_CALL_LOG
#define SYS_CALL_LOG(format, ...) 0  ///< 系统打印日志标志
#endif
void *OSAL_ApiCreate(char *name, void *fn);
void *OSAL_ApiCallStart(char *name, char *path);
void OSAL_ApiCallStop(void);

/** @brief   调用系统API  */
#define SYS_CALL(api, args...) ({                                      \
    typeof(api(args)) ret;                                             \
    void *api_fn = (void*)OSAL_ApiCallStart(#api, __FILE__);           \
                                                                       \
    ret = (api_fn != NULL) ? (((typeof(api)*)api_fn)(args)):           \
    ((typeof(ret))SYS_CALL_LOG("SYS_CALL(%s, %s);\r\n", #api, #args)); \
                                                                       \
    (api_fn != NULL) ? (OSAL_ApiCallStop()) : (void)0;                 \
                                                                       \
    (api_fn != NULL) ? ret : (typeof(ret))0;                           \
})

/** @brief   创建系统API  */
#define SYS_API(api) OSAL_ApiCreate(#api, api)



/* OSPORT加密通信相关API */
#ifdef KOS_PARAM_OSPORT_CRYPTO
uint16_t OSAL_OsportProbeRequest(uint16_t dev_type, uint8_t devNum, uint8_t *esn);                           //< Probe请求（主设备底层调用）
uint8_t OSAL_OsportGetDefaultAccount(uint8_t *esn);                                                          //< 获取默认的账户esn（子设备底层调用）
void OSAL_OsportSetDefaultAccount(uint8_t devNum, uint8_t *esn, uint8_t *pwd1);                              //< 设置默认的账户（应用层产测调用）
ErrorStatus OSAL_OsportAddAccount(uint8_t devNum, uint8_t *esn, uint8_t *pwd1, void (*add_cb)(ErrorStatus)); //< 阿泼泼添加子设备
ErrorStatus OSAL_OsportDeleteAccount(uint8_t devNum, uint8_t *esn);                                          //< 阿泼泼删除子设备
void OSAL_OsportReconnect(void);
void OSAL_OsportAdv(void);          //产测启动广播
void OSAL_OsportDisconnect(void);   //断开连接
void OSAL_OsportCalibration(uint8_t *msg);      //产测蓝牙频偏校准
void OSAL_OsportGetBleGatt(uint8_t *data);     //产测读蓝牙gatt和频偏
void OSAL_OsportGetBleMac(uint8_t *data);       //获取蓝牙地址
ErrorStatus OSAL_OsportSetAccountDevInfo(uint8_t *esn,void *data);
ErrorStatus OSAL_OsportGetAccountDevInfo(uint8_t *esn,void *data);

#endif

#endif /* __OSAL_H__ */
